﻿using JSONDB.helpers;
using MongoDB.Driver;
using NLog;
using OPCService.Job;
using OPCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ThreadTimer = System.Threading.Timer;
using WindowTimer = System.Windows.Forms.Timer;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using JSONItem = JSONDB.Item; //别名
using OpcItem = OPCService.Model.Item;

namespace OPCService.Service
{
    class GrateLineService
    {
        private WindowTimer watcherTimer1;
        private string TagJdwCnName1;  //进到位信号
        private string TagTdwCnName2;  //退到位信号
        private string TagLpForCnName3;//炉排前进
        private string TagLpBacCnName4;//炉排后退
        private static string jsonconfig = AppDomain.CurrentDomain.BaseDirectory + @ConfigHelper.ReadConfig("jsondb");
        private static readonly String opc500name = ConfigHelper.ReadConfig("Opc500DataCollection");
        private static readonly String colName = ConfigHelper.ReadConfig("colname");
        private static JsonDBHelper jsonDBHelper = new JsonDBHelper(jsonconfig);
        private static MongoDbHelper mongoDbHelper = new MongoDbHelper();
        private static readonly Logger logger = NLog.LogManager.GetCurrentClassLogger();
        private bool TDWFlag = false;    //炉排退到位标识
        private int TDWTime = 0;  //炉排退到位累计时间


        public GrateLineService(string tagJdwCnName1, string tagTdwCnName2, string tagLpForCnName3, string tagLpForCnName4)
        {
            TagJdwCnName1 = tagJdwCnName1;
            TagTdwCnName2 = tagTdwCnName2;
            TagLpForCnName3 = tagLpForCnName3;
            TagLpBacCnName4 = tagLpForCnName4;

            if (!tagJdwCnName1.Contains("炉排4号顺推进到位信号"))
            {
                Init();
            }
        }

        private void Init()
        {
            //1、后退指令
            string lp_bac_tag_name = GetPeriodTagname(TagLpBacCnName4);
            logger.Info(TagLpBacCnName4 + "<===========Init lp tag===========>" + lp_bac_tag_name);

            //2、不管当前位置，设置正的炉排速度（后退指令），使其到退到位，再设置负的炉排速度（前进指令），使其到进到位，再设置炉排速度为0（-> | <- |）
            SetOpcTagValue(lp_bac_tag_name, true);//后退指令

            //初始化标识
            TDWFlag = false;
            TDWTime = 0;
            logger.Info("计时0");
            //计时器轮询监听退到位信号，检测到则给前进指令，否则30秒超时未检测到退到位信号，则直接给一次前进指令
            watcherTimer1 = new WindowTimer { Interval = 500 };
            watcherTimer1.Tick += WatcherTimer_Tick1;
            watcherTimer1.Start();
        }

        /**
         * 初始以正的炉排速度到退到位，设置负的炉排速度（前进指令）到使其到进到位
         * 监听退到位，到位时设置负的炉排速度，再计时器轮询监听进到位，到位时设置炉排速度为0（自动复位，自动设置为0）
         */
        private void WatcherTimer_Tick1(object sender, EventArgs e)
        {
            logger.Info("计时循环");
            //累计计时
            TDWTime += 500;

            //获取退到位点位
            double tdw_val = GetTagnameLatestValue(TagTdwCnName2);
            string lp_for_tag_name = GetPeriodTagname(TagLpForCnName3);
            //logger.Info(lp_for_tag_name + "<===========Tick1 tdw===========>" + tdw_val);
            if (tdw_val == 1)
            {
                TDWFlag = true;
                logger.Info(lp_for_tag_name + "<===========Tick1 lp tag===========>" + TagLpForCnName3);

                //给前进信号
                SetOpcTagValue(lp_for_tag_name, true);

                // 5秒后再执行一次前进指令
                var timer = new ThreadTimer(_ =>
                {
                    SetOpcTagValue(lp_for_tag_name, true);
                }, null, TimeSpan.FromSeconds(5), Timeout.InfiniteTimeSpan);
            }

            //30秒内未检测到退到位信号，则给一次前进指令
            if (!TDWFlag && TDWTime >= 30000)
            {
                logger.Info("timeout");
                SetOpcTagValue(lp_for_tag_name, true);
                watcherTimer1.Stop(); //停止退到位监听
            }
        }

        //获取需要计算周期的点位
        public static string GetPeriodTagname(string cn_name)
        {
            string tag_name = "";
            int total;
            List<JSONItem> items = jsonDBHelper.GetItems(opc500name, 200, 1, out total);
            foreach (JSONItem item in items)
            {
                if (cn_name.Equals(item.name))
                {
                    tag_name = item.value;
                    break;
                }
            }
            return tag_name;
        }

        //获取tag最新数据
        public static double GetTagnameLatestValue(string cn_name)
        {
            double val = 0;
            string tag_name = GetPeriodTagname(cn_name);
            // 创建构建器
            var builder = Builders<OpcItem>.Filter;

            // 构建排序方式：按 datetime 倒序
            var sort = Builders<OpcItem>.Sort.Descending(x => x.datetime);

            FilterDefinition<OpcItem> filter = builder.Eq("tag_name", tag_name);
            List<OpcItem> datalist = mongoDbHelper.findLimit<OpcItem>(colName, filter, sort, 3);
            if (datalist.Count > 0)
            {
                foreach (OpcItem data in datalist)
                {
                    val = data.value;
                    break;
                }
            }

            return val;
        }

        //设置OPC tag值
        private void SetOpcTagValue(string tag_name, object value)
        {
            bool cbAotoWrite = Properties.Settings.Default.cbAotoWrite;
            Task.Run(async () =>
            {
                try
                {
                    logger.Info(tag_name + "<===========setOpcTagValue===========>" + value);
                    if (cbAotoWrite)
                    {
                        await Opc500DataCollection.WriteData(tag_name, value);
                    }
                }
                catch (Exception ex)
                {
                    logger.Info(tag_name + "<===========setOpcTagValue error===========>");
                }
            });
        }

        public void Dispose()
        {
            watcherTimer1.Dispose();
        }
    }
}
